using System;
using Synapse.Framework.Notifier;
using Synapse.Framework.Pipe.BusinessObjects;
using Synapse.Framework.Pipe.Filters;
using Synapse.Framework.Pipe.Operations;

namespace Synapse.Framework.Pipe.PipeLines
{
    internal class OperationInstance<TFilter, TInput, TPump> : IOperation<TFilter, TInput, TPump>
    {
        private readonly IResolver resolver;
        private readonly PipeLine pipeLine;
        private readonly TFilter filter;
        private readonly INotifier notifier;

        public OperationInstance(IResolver resolver, PipeLine pipeLine, TFilter filter, INotifier notifier)
        {
            this.resolver = resolver;
            this.pipeLine = pipeLine;
            this.filter = filter;
            this.notifier = notifier;
        }

        public IFilter<TOutput, TPump> Out<TOutput>(Func<TFilter, Func<TInput, TOutput>> func)
        {
            pipeLine.Add(new FilterAOP<TInput, TOutput>(new OperationFuncAdapter<TInput, TOutput>(func(filter)),notifier));
            return new Filter<TOutput, TPump>(resolver, pipeLine,notifier);
        }

        public IFilter<TOutput, TPump> OutObject<TOutput>(Func<TFilter, Func<TInput, _<TOutput>>> func)
        {
            pipeLine.Add(new FilterAOP<TInput, TOutput>(new Operations.OperationFunc<TInput, TOutput>(func(filter)), notifier));
            return new Filter<TOutput, TPump>(resolver, pipeLine, notifier);
        
        }

    }

    internal class OperationFunc<TInput, TPump> : IOperationFunc<TInput, TPump>
    {
        private readonly IResolver resolver;
        private readonly PipeLine pipeLine;
        private readonly INotifier notifier;

        public OperationFunc(IResolver resolver, PipeLine pipeLine, INotifier notifier)
        {
            this.resolver = resolver;
            this.pipeLine = pipeLine;
            this.notifier = notifier;
        }

        public IFilter<TOutput, TPump> Out<TOutput>(Func<TInput, TOutput> func)
        {
            pipeLine.Add(new FilterAOP<TInput, TOutput>(new OperationFuncAdapter<TInput, TOutput>(func), notifier));
            return new Filter<TOutput, TPump>(resolver, pipeLine, notifier);
        }

        public IFilter<TOutput, TPump> OutObject<TOutput>(Func<TInput, _<TOutput>> func)
        {
            pipeLine.Add(new FilterAOP<TInput, TOutput>(new Operations.OperationFunc<TInput, TOutput>(func), notifier));
            return new Filter<TOutput, TPump>(resolver, pipeLine, notifier);
        }
    }


}